<?php

/**
 * SimplifyPHP Framework
 *
 * This file is part of SimplifyPHP Framework.
 *
 * SimplifyPHP Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SimplifyPHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 */

require_once ('api/IQueryObject.php');

/**
 *
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 * @package Simplify_Kernel_DAO
 */
abstract class QueryObject implements IQueryObject
{

  const JOIN_INNER = 'INNER JOIN';

  const JOIN_LEFT = 'LEFT JOIN';

  const JOIN_RIGHT = 'RIGHT JOIN';

  protected $fields;

  protected $table;

  protected $join = array();

  protected $groupBy;

  protected $having;

  protected $where = array();

  protected $orderBy = array();

  protected $limit;

  protected $offset;

  protected $sql;

  protected $__sql = null;

  /**
   *
   * @var IDataAccessObject
   */
  protected $dao;

  /**
   *
   * @param IDataAccessObject $dao
   * @return void
   */
  public function __construct($dao)
  {
    $this->dao = $dao;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#select($fields)
   */
  public function select($fields = null)
  {
    if (func_num_args() > 1) {
      $fields = func_get_args();
    }

    $this->fields = $fields;

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#from($table)
   */
  public function from($table = null)
  {
    if (func_num_args() > 1) {
      $table = func_get_args();
    }

    $this->table = $table;

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#join($table, $condition, $type)
   */
  public function join($table = null, $condition = null, $type = null)
  {
    if (empty($type)) {
      $type = QueryObject::JOIN_INNER;
    }

    $this->join[] = array(
      $table, $condition, $type
    );

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#groupBy($s)
   */
  public function groupBy($s = null)
  {
    $this->groupBy = $s;

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#having($s)
   */
  public function having($s = null)
  {
    $this->having = $s;

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#where($s)
   */
  public function where($s = null)
  {
    if (func_num_args() > 1) {
      $s = func_get_args();

      $this->where = array_merge($this->where, $s);
    }
    else {
      $this->where[] = $s;
    }

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#orderBy($s, $direction)
   */
  public function orderBy($s = null, $direction = 'ASC')
  {
    if (preg_match('/([a-z_]*\.?[a-z_]+)\s+(asc|desc)/i', $s, $o)) {
      $s = $o[1];
      $direction = $o[2];
    }

    $this->orderBy[] = array(
      $s, $direction
    );

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#limit($limit)
   */
  public function limit($limit = null)
  {
    $this->limit = ( int ) $limit;

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#offset($offset)
   */
  public function offset($offset = null)
  {
    $this->offset = ( int ) $offset;

    $this->__sql = null;
    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#sql($sql)
   */
  public function sql($sql = null)
  {
    $this->sql = $sql;

    $this->__sql = null;
    return $this;
  }

  public function setParams(array $params = null)
  {
    $query =& $this;

    if (isset($params['fields'])) {
      $query->select($params['fields']);
    }

    if (isset($params['orderBy'])) {
      $query->orderBy($params['orderBy']);
    }

    if (isset($params['limit'])) {
      $query->limit($params['limit']);
    }

    if (isset($params['offset'])) {
      $query->offset($params['offset']);
    }

    if (isset($params['where'])) {
      if (is_array($params['where'])) {
        foreach ($params['where'] as $where) {
          $query->where($where);
        }
      }
      else {
        $query->where($params['where']);
      }

      return $this;
    }

    if (isset($params['groupBy'])) {
      $query->offset($params['groupBy']);
    }

    if (isset($params['having'])) {
      $query->offset($params['having']);
    }
  }

  public static function buildInsert($data, $wildcard = null)
  {
    $fields = array();
    $values = array();

    foreach ($data as $k => $v) {
      $fields[] = $k;
      
      if ($wildcard === false) {
        $values[] = DAO::getInstance()->quote($v);
      } elseif (is_string($wildcard)) {
        $values[] = $wildcard;
      } else {
        $values[] = ':' . $k;
      }
    }

    return empty($fields) ? '' : '(' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')';
  }

  public static function buildUpdate($data, $wildcard = null)
  {
    $fields = array();

    foreach ($data as $k => $v) {
      //$fields[] = $k . ' = ' . ($wildcard ? $wildcard : DAO::getInstance()->quote($v));
      if ($wildcard === false) {
        $fields[] = $k . ' = ' . DAO::getInstance()->quote($v);
      } elseif (is_string($wildcard)) {
        $fields[] = $k . ' = ' . $wildcard;
      } else {
        $fields[] = $k . ' = :' . $k;
      }
    }

    return ' SET ' . implode(', ', $fields) . ' ';
  }

}

?>